#include "ItemDatabase.h"

#include "boost_filesystem.h"

#include "Conversions.h"
#include "Item.h"
#include "Logger.h"
#include "Singleton.h"
#include <TinyXML\tinyxml.h>

bool ItemDatabase::initialised = false;
ItemDatabase ItemDatabase::instance = ItemDatabase();

void ItemDatabase::initialise(std::string saveName)
{
    BEGIN_INITIALISATION("Initialising ItemDatabase...");

    // load entries from file
    instance.readFile(saveName);

    END_INITIALISATION("... ItemDatabase initialised.");
}

ItemDatabase& ItemDatabase::get()
{
    GET_INSTANCE("ItemDatabase");
}

void ItemDatabase::cleanUp()
{
    BEGIN_CLEAN_UP("ItemDatabase");

    instance.entries.clear();

    END_CLEAN_UP("ItemDatabase");
}

ItemDatabase::ItemDatabase()
{
}

const ItemData& ItemDatabase::getData(int item_id)
{
    idata_map::const_iterator item = entries.find(item_id);
    if(item == entries.end())
    {
        throw std::runtime_error("Invalid item ID (" +
            Conversions::toString(item_id) +
            ") in ItemDatabase::getData().");
    }
    return item->second;
}

const ItemData& ItemDatabase::getData(const Item& item)
{
    return getData(item.getId());
}

void ItemDatabase::addItemData( const ItemData& itemData, int id )
{
    entries.insert(std::pair<int, ItemData>(id, itemData));
}

void ItemDatabase::writeFile( std::string saveName ) const
{
    //Document
    TiXmlDocument idDoc;
    //Declaration
    TiXmlDeclaration* declaration = new TiXmlDeclaration("1.0", "", "");
    idDoc.LinkEndChild(declaration);
    //Root
    TiXmlElement* idbElement = new TiXmlElement("ITEM_DATABASE");
    idDoc.LinkEndChild(idbElement);
    //ItemDatas
    TiXmlElement* itemDataElement = new TiXmlElement("ItemDatas");
    idbElement->LinkEndChild(itemDataElement);
    //Adding each item data to xml
    for (idata_map::const_iterator item = entries.begin();item != entries.end(); ++item)
    {
        TiXmlElement* idataElement = new TiXmlElement("ItemData");
        idataElement->SetAttribute("id", item->first);
        idataElement->SetAttribute("imageId", item->second.getIcon()->getImageId());
        idataElement->SetAttribute("weight", item->second.getWeight());
        idataElement->SetAttribute("value", item->second.getValue());
        idataElement->SetAttribute("maxStack", item->second.getMaxStack());
        itemDataElement->LinkEndChild(idataElement);
    }
    //Save final xml file
    idDoc.SaveFile("xml/" + saveName + "/ItemDatabase.xml");
}

void ItemDatabase::save(std::string saveName) const
{
    writeFile(saveName);
}

bool ItemDatabase::readFile( std::string saveName )
{
    TiXmlDocument idDoc("xml/" + saveName + "/ItemDatabase.xml");
    if (!idDoc.LoadFile())
    {
        throw std::runtime_error("xml/" + saveName + "/ItemDatabase.xml can not be opened.");
        return false;
    }
    TiXmlElement* rdbElement = idDoc.RootElement();
    TiXmlElement* idatasElement = rdbElement->FirstChildElement("ItemDatas");
    TiXmlElement* idataElement = idatasElement->FirstChildElement("ItemData");
    for(idataElement; idataElement; idataElement = idataElement->NextSiblingElement())
    {
        int id, imageId, maxStack, weight, value;
        idataElement->QueryIntAttribute("id", &id);
        idataElement->QueryIntAttribute("imageId", &imageId);
        idataElement->QueryIntAttribute("value", &value);
        idataElement->QueryIntAttribute("maxStack", &maxStack);
        idataElement->QueryIntAttribute("weight", &weight);
        addItemData(ItemData(AnimatedSpritePtr(new AnimatedSprite(imageId)), weight, value, maxStack), id);
    }  
    return true;
}
